package cn.sdfykjyxgs.syncommon.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.FileUtil;
import cn.sdfykjyxgs.syncommon.entity.FileChangeLog;
import cn.sdfykjyxgs.syncommon.entity.FileChangeLogError;
import cn.sdfykjyxgs.syncommon.mapper.FileChangeLogErrorMapper;
import cn.sdfykjyxgs.syncommon.mapper.FileChangeLogMapper;
import cn.sdfykjyxgs.syncommon.service.FileChangeLogService;
import cn.sdfykjyxgs.syncommon.util.FileLogic;
import cn.sdfykjyxgs.syncommon.util.LocalFileChangeError;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.SneakyThrows;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributeView;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class FileChangeLogServiceImpl extends ServiceImpl<FileChangeLogMapper, FileChangeLog> implements FileChangeLogService {
    @Resource
    private FileChangeLogErrorMapper errorMapper;

    /**
     * 判断文件是否存在记录
     *
     * @param ulr
     * @param name
     * @return
     */
    @Override
    public boolean fileExisted(String ulr, String name) {
        File file = new File(ulr + "\\" + name);
        String fileKey = getFileKey(file, true);
        QueryWrapper<FileChangeLog> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(FileChangeLog::getKey, fileKey)
                .eq(FileChangeLog::getUrl, ulr)
                .eq(FileChangeLog::getName, name);
        int count = super.count(queryWrapper);
        return count == 0 ? false : true;
    }

    /**
     * 判断记录中的文件是否为最新文件
     *
     * @param ulr
     * @param name
     * @return
     */
    @Override
    public boolean fileLogIsLatest(String ulr, String name) {
        return false;
    }

    /**
     * 新增文件日志
     *
     * @param ulr
     * @param name
     * @return
     */
    @Override
    public FileChangeLog saveFileLog(String ulr, String name) {
        FileChangeLog fileChangeLog = new FileChangeLog();
        //判断是文件还是文件夹
        File file = new File(ulr + "\\" + name);
        int fileType = file.isFile() ? 1 : 0;
        String fileKey = getFileKey(file, true);
        //判断fileKey 是否存在于本地数据库中 如果存在且文件最后日志状态为删除则为移动文件操作
        QueryWrapper<FileChangeLog> queryWrapper = new QueryWrapper<>();
        FileChangeLog one = null;
        queryWrapper.lambda()
                .eq(FileChangeLog::getKey, fileKey)
                .eq(FileChangeLog::getLogic, FileLogic.DELETE)
                .orderByDesc(FileChangeLog::getId).last("limit 1");
        one = super.getOne(queryWrapper);
        if (one != null) {
            String historyName = one.getName();
            one.setLogic(FileLogic.MOVE);
            one.setTime(new Date());
            one.setRemark(historyName);
            one.setName(name);
            one.setKeyHierarchy(getKeyHierarchy(ulr, name));
            super.updateById(one);
            return one;
        } else {
            queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda()
                    .eq(FileChangeLog::getUrl, ulr)
                    .eq(FileChangeLog::getName, name)
                    .eq(FileChangeLog::getKey, fileKey)
                    .orderByDesc(FileChangeLog::getId);

            one = super.getOne(queryWrapper);
            int version = 1;
            if (one != null) version += one.getVersion();


            fileChangeLog.setKey(fileKey);
            fileChangeLog.setUrl(ulr);
            fileChangeLog.setName(name);
            fileChangeLog.setFileType(fileType);
            fileChangeLog.setKeyHierarchy(getKeyHierarchy(ulr, name));
            fileChangeLog.setLogic(FileLogic.INSERT);
            fileChangeLog.setTime(new Date());
            Date date = new Date(file.lastModified());
            fileChangeLog.setFileLatestTime(date);
            fileChangeLog.setVersion(version);
            fileChangeLog.setSynStatus(false);
            try {
                boolean save = super.save(fileChangeLog);

            } catch (Exception e) {
                e.printStackTrace();
                LocalFileChangeError.errorLists.add(fileChangeLog);
                FileChangeLogError fileChangeLogError = BeanUtil.copyProperties(fileChangeLog, FileChangeLogError.class);
                errorMapper.insert(fileChangeLogError);
            }
            return fileChangeLog;
        }

    }

    /**
     * 删除文件日志
     *
     * @param ulr
     * @param name
     * @return
     */
    @Override
    public FileChangeLog removeFileLog(String ulr, String name) {
        QueryWrapper<FileChangeLog> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(FileChangeLog::getUrl, ulr)
                .eq(FileChangeLog::getName, name)
                .orderByDesc(FileChangeLog::getId).last("limit 1");
        FileChangeLog one = super.getOne(queryWrapper);
        if (one != null) one.setVersion(one.getVersion() + 1);
        one.setId(null);
        one.setLogic(FileLogic.DELETE);
        one.setTime(new Date());
        super.save(one);
        return one;
    }

    /**
     * 文件内容被修改日志
     *
     * @param ulr
     * @param name
     * @return
     */
    @Override
    public FileChangeLog fileModifiedLog(String ulr, String name) {
        FileChangeLog fileChangeLog = new FileChangeLog();
        //判断是文件还是文件夹
        File file = new File(ulr + "\\" + name);
        String fileKey = getFileKey(file, true);
        int fileType = file.isFile() ? 1 : 0;
        Date date = new Date(file.lastModified());
        QueryWrapper<FileChangeLog> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(FileChangeLog::getKey, fileKey)
                .orderByDesc(FileChangeLog::getId).last(" limit 1");
        FileChangeLog one = super.getOne(queryWrapper);
        int version = 1;
        if (one != null) {
            version += one.getVersion();
            fileChangeLog.setKey(one.getKey());
            fileChangeLog.setUrl(ulr);
            fileChangeLog.setName(name);
            fileChangeLog.setFileType(fileType);
            fileChangeLog.setLogic(FileLogic.UPDATE);
            fileChangeLog.setTime(new Date());
            fileChangeLog.setKeyHierarchy(one.getKeyHierarchy());
            fileChangeLog.setFileLatestTime(date);
            fileChangeLog.setVersion(version);
            fileChangeLog.setSynStatus(false);
            super.save(fileChangeLog);
        }
        return fileChangeLog;
    }

    /**
     * 文件名称被修改日志
     *
     * @param ulr
     * @param name
     * @param oldName
     * @return
     */
    @Override
    public FileChangeLog fileRenamedLog(String ulr, String name, String oldName) {
        //判断是文件还是文件夹
        File file = new File(ulr + "\\" + name);
        int fileType = file.isFile() ? 1 : 0;
        String fileKey = getFileKey(file, true);
        QueryWrapper<FileChangeLog> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(FileChangeLog::getKey, fileKey)
                .eq(FileChangeLog::getUrl, ulr)
                .eq(FileChangeLog::getName, oldName)
                .orderByDesc(FileChangeLog::getId).last(" limit 1");

        FileChangeLog one = super.getOne(queryWrapper);
        int version = 1;
        if (one != null) version += one.getVersion();

        FileChangeLog fileChangeLog = new FileChangeLog();
        fileChangeLog.setKey(fileKey);
        fileChangeLog.setUrl(ulr);
        fileChangeLog.setName(name);
        fileChangeLog.setFileType(fileType);
        fileChangeLog.setLogic(FileLogic.RENAMED);
        fileChangeLog.setKeyHierarchy(getKeyHierarchy(ulr, name));
        fileChangeLog.setTime(new Date());
        Date date = new Date(file.lastModified());
        fileChangeLog.setFileLatestTime(date);
        fileChangeLog.setVersion(version);
        fileChangeLog.setRemark(oldName);
        fileChangeLog.setSynStatus(false);
        boolean save = super.save(fileChangeLog);
        return fileChangeLog;
    }

    /**
     * 修改文件日志同步状态
     *
     * @param fileId
     * @return
     */
    @Override
    public boolean synStatusFileLog(Integer fileId) {
        FileChangeLog byId = this.getById(fileId);
        byId.setSynStatus(true);
        this.updateById(byId);
        return false;
    }

    /**
     * 返回待同步日志记录
     *
     * @return
     */
    @Override
    public Page<FileChangeLog> syncData() {
        Page<FileChangeLog> page = new Page<>(1, 10);
        QueryWrapper<FileChangeLog> queryWrapper = new QueryWrapper<>();
        Page<FileChangeLog> page1 = this.page(page, queryWrapper);
        return page1;
    }

    @Override
    public List<FileChangeLog> syncDataList() {
        QueryWrapper<FileChangeLog> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(FileChangeLog::getSynStatus, false).orderByAsc(FileChangeLog::getId);
        List<FileChangeLog> list = this.list(queryWrapper);
        return list;
    }

    @Override
    public FileChangeLog queryById(Long fileId) {
        FileChangeLog fileChangeLog = this.getById(fileId);
        return fileChangeLog;
    }

    @Override
    public void refreshStatus(Long fileId) {
        FileChangeLog fileChangeLog = queryById(fileId);
        if (fileChangeLog != null) {
            fileChangeLog.setSynStatus(true);
            updateById(fileChangeLog);
        }
    }

    @SneakyThrows
    public String getFileKey(File file, Boolean isIn) {
        // 指定自己的目标文件
        // 根据文件的绝对路径获取Path
        Path path = Paths.get(file.getAbsolutePath());
        // 根据path获取文件的基本属性类
        BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
        // 从基本属性类中获取文件创建时间
        FileTime creationTime = attrs.creationTime();
        FileTime modifiedTime = attrs.lastModifiedTime();
        FileTime accessTime = attrs.lastAccessTime();
        // 将文件创建时间转成毫秒
        long millis = creationTime.toMillis();
        if (isIn) {
            Integer seed = 0;
            Long key = genKeySeed(millis, seed);
            if (seed != 0) {
                FileTime from = FileTime.from(key, TimeUnit.MILLISECONDS);
                BasicFileAttributeView fileAttributeView = Files.getFileAttributeView(path, BasicFileAttributeView.class);
                fileAttributeView.setTimes(modifiedTime, accessTime, from);
            }
            return key.toString();
        }
        return millis + "";
    }

    @SneakyThrows
    public Long genKeySeed(Long millis, Integer seed) {
        {
            millis = millis + seed;
            QueryWrapper<FileChangeLog> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(FileChangeLog::getKey, millis).eq(FileChangeLog::getLogic, FileLogic.INSERT).last("limit 1");
            int count = this.count(queryWrapper);
            if (count != 0) {
                int i = seed.intValue() + 1;
                return genKeySeed(millis, i);
            }
        }
        return millis;
    }

    public String getKeyHierarchy(String ulr, String name) {
        String tempUrl = ulr + "\\";
        if (name.indexOf("\\") != -1) {
            String substring = name.substring(0, name.lastIndexOf("\\"));
            tempUrl += substring;
            QueryWrapper<FileChangeLog> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(FileChangeLog::getName, substring).eq(FileChangeLog::getLogic, FileLogic.INSERT).last("limit 1");
            FileChangeLog one = this.getOne(queryWrapper);
            if (one != null) return one.getKey();
        }
        File file = new File(tempUrl);
        String fileKey = getFileKey(file, false);

        return fileKey;
    }

    public static void main(String[] args) throws IOException {
        File file = FileUtil.file("D:\\test\\amdy_large_screen_call\\.idea\\caches");
        Path path = Paths.get(file.getAbsolutePath());
        // 根据path获取文件的基本属性类
        BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
        // 从基本属性类中获取文件创建时间
        FileTime creationTime = attrs.creationTime();
        FileTime modifiedTime = attrs.lastModifiedTime();
        FileTime accessTime = attrs.lastAccessTime();
        // 将文件创建时间转成毫秒
        long millis = creationTime.toMillis();

        //---------------------------
        FileTime from = FileTime.from(millis + 1, TimeUnit.MILLISECONDS);
        BasicFileAttributeView fileAttributeView = Files.getFileAttributeView(path, BasicFileAttributeView.class);
        fileAttributeView.setTimes(modifiedTime, accessTime, from);

        File file2 = FileUtil.file("D:\\test\\amdy_large_screen_call\\.idea\\caches\\gradle_models.ser");
        Path path2 = Paths.get(file2.getAbsolutePath());
        // 根据path获取文件的基本属性类
        BasicFileAttributes attrs2 = Files.readAttributes(path2, BasicFileAttributes.class);
        // 从基本属性类中获取文件创建时间
        FileTime fileTime2 = attrs2.creationTime();
        // 将文件创建时间转成毫秒
        long millis2 = fileTime2.toMillis();
        System.out.println(123);

    }

    public void sss() {
        return;
    }
}
